package cc.rengu.oltp.service.base;

import cc.rengu.jradp.application.BulletinBoard;
import cc.rengu.jradp.application.ServiceEntity;
import cc.rengu.jradp.asynnotify.AsynNotify;
import cc.rengu.jradp.schedule.AbstractSchedule;
import cc.rengu.jradp.schedule.Schedule;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.utility.annotation.BIZ_RESULT;
import cc.rengu.oltp.utility.util.GlobalTransUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import cc.rengu.utility.objectpool.ObjectPool;
import com.alibaba.fastjson.JSON;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 通道调用原子服务实现基类
 * Created by wangcheng on 2021/3/6 17:47
 */
public abstract class ChannelBaseService<R, S, T> {
    public final RgLogger rglog = RgLog.getLogger(this.getClass().getName());
    public static final String FIRST_CHANNEL_CALL_INDEX = "0000";
    private static final String LOCAL_SERVICE = "LOCAL";
    private static final String CHANNEL_CALL_RESULT = "CHANNEL_CALL_RESULT";
    private int REPEAT_CALL_INDEX = 0;

    /**
     * 通道服务调用
     *
     * @param txnInfo   交易配置信息
     * @param orderInfo 订单信息
     * @param bizScene  业务场景
     * @param request   交易请求对象
     * @throws Exception 异常
     */
    public void callService(TxnInfo txnInfo, OrderInfo orderInfo, String bizScene, T request) throws Exception {
        if (null != txnInfo && null != txnInfo.getSrcTxnAuthCfg() && null != txnInfo.getChannelCallCfgList()) {
            callServiceCore(txnInfo, FIRST_CHANNEL_CALL_INDEX, null, orderInfo, bizScene, request);
        }
    }

    /**
     * 通道服务调用核心处理
     *
     * @param txnInfo       交易配置信息
     * @param callIndex     当前调用序号
     * @param lastCallIndex 上次调用序号
     * @param orderInfo     订单信息
     * @param bizScene      业务场景
     * @param request       交易请求对象
     * @throws Exception 异常
     */
    private void callServiceCore(TxnInfo txnInfo, String callIndex, String lastCallIndex, OrderInfo orderInfo, String bizScene, T request) throws Exception {
        /* Step1：通道调用场景识别返回对应的通道服务配置 */
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(txnInfo, bizScene, callIndex, request);
        rglog.info("---------------> 正在调用通道{}的【{}-{}】服务 <---------------", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
        /* Step2：通道服务调用前业务检查 */
        CheckResultEnum checkResultEnum = channelCallPreCheck(txnInfo, channelCallCfg, orderInfo, request);
        if (checkResultEnum.equals(CheckResultEnum.REFUSE)) {
            /* Step2.1：判断当前通道调用失败是否会影响交易 */
            if (AppParamConstant.YES.equals(channelCallCfg.getImpactTxnFlag())) {
                rglog.error("调用通道<{}>的<{}-{}>服务前业务检查失败，交易结束!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            } else {
                rglog.info("通道标识为<{}>,调用序号为<{}>的通道服务调用失败不影响交易结果，继续下个通道的调用！", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex());
                callNextChannelService(txnInfo, channelCallCfg.getCallChannelId(), channelCallCfg.getNextCallIndex(), channelCallCfg.getCallIndex(), lastCallIndex, orderInfo, bizScene, request);
            }
        } else if (checkResultEnum.equals(CheckResultEnum.NEXT)) {
            rglog.info("通道标识为<{}>,调用序号为<{}>的通道服务基于业务规则检查后无需调用，继续下个通道的调用！", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex());
            callNextChannelService(txnInfo, channelCallCfg.getCallChannelId(), channelCallCfg.getNextCallIndex(), channelCallCfg.getCallIndex(), lastCallIndex, orderInfo, bizScene, request);
        } else if (checkResultEnum.equals(CheckResultEnum.FAILURE)) {
            rglog.info("通道标识为<{}>,调用序号为<{}>的通道服务基于业务规则检查后无需调用，但要模拟当前通道调用失败的后续通道调用！", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex());
            callNextChannelService(txnInfo, channelCallCfg.getCallChannelId(), channelCallCfg.getFailCallIndex(), channelCallCfg.getCallIndex(), lastCallIndex, orderInfo, bizScene, request);
        } else if (checkResultEnum.equals(CheckResultEnum.FINISH)) {
            rglog.info("通道标识为<{}>,调用序号为<{}>的通道服务基于业务规则检查后不需要继续调用下个通道，交易正常结束!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex());
        } else if (checkResultEnum.equals(CheckResultEnum.REPEAT)) {
            rglog.info("通道标识为<{}>,调用序号为<{}>的通道服务基于业务场景在调用完成后继续当前通道服务的调用!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex());
            if (this.REPEAT_CALL_INDEX > 20) {
                rglog.error("通道标识为<{}>,调用序号为<{}>的通道服务调用次数已超过系统允许的最大重复调用次数!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            } else {
                rglog.info("通道标识为<{}>,调用序号为<{}>的通道服务正在进行第【{}】次调用!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallIndex(), this.REPEAT_CALL_INDEX);
                TransStatusEnum transStatusEnum = callChannelService(txnInfo, callIndex, channelCallCfg, orderInfo, request);
                this.REPEAT_CALL_INDEX++;
                /* 当前通道调用成功后继续当前通道的调用，否则基于是否影响交易判断是否拒绝交易 */
                if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)) {
                    callServiceCore(txnInfo, callIndex, lastCallIndex, orderInfo, bizScene, request);
                } else if (AppParamConstant.YES.equals(channelCallCfg.getImpactTxnFlag())) {
                    rglog.error("调用通道<{}>的<{}-{}>服务失败，交易结束!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
                    String chnlCallResultKey = CHANNEL_CALL_RESULT + channelCallCfg.getCallChannelId() + channelCallCfg.getCallIndex() + channelCallCfg.getCallChannelTxn();
                    Map<String,String> respValueMap = (Map<String, String>) GlobalTransUtil.getCacheValue(chnlCallResultKey);
                    if (null != respValueMap && !StringUtil.isEmptyOrNull(respValueMap.get(TreeNodeConstant.RESP_CODE))){
                        if (OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(respValueMap.get(TreeNodeConstant.RESP_CODE))) {
                            throw new BizException(TransStatusEnum.TRANS_TIMEOUT.equals(transStatusEnum) ? OltpRpcdEnum.BIZ_PROCESS_TIMEOUT : OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                        }else {
                            throw new BizException(respValueMap.get(TreeNodeConstant.RESP_CODE), respValueMap.get(TreeNodeConstant.RESP_DESC));
                        }
                    }else {
                        throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                    }
                }
            }
        } else if (checkResultEnum.equals(CheckResultEnum.PASSED)) {
            if (LOCAL_SERVICE.equals(channelCallCfg.getCallChannelId())) {
                /* 本地服务调用 */
                callLocalService(txnInfo, channelCallCfg, orderInfo, bizScene, request);
            } else {
                /* 通道服务调用 */
                TransStatusEnum transStatusEnum = callChannelService(txnInfo, callIndex, channelCallCfg, orderInfo, request);
                /* 基于交易通道服务调用配置调用下一个通道服务 */
                String nextCallIndex = channelCallCfg.getFailCallIndex();
                if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)) {
                    nextCallIndex = channelCallCfg.getNextCallIndex();
                } else if (TransStatusEnum.TRANS_TIMEOUT.equals(transStatusEnum)) {
                    nextCallIndex = channelCallCfg.getTimeoutCallIndex();
                }
                /* 基于通道调用结果进行后续处理控制 */
                if (!TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)){
                    if (AppParamConstant.YES.equals(channelCallCfg.getImpactTxnFlag())) {
                        /* 当前通道调用失败影响交易且配置了失败或超时的调用序号，则先调用异常处理流程，然后返回通道调用失败 */
                        if (!StringUtil.isEmptyOrNull(nextCallIndex)) {
                            try {
                                callServiceCore(txnInfo, nextCallIndex, callIndex, orderInfo, bizScene, request);
                            } catch (Exception e) {
                                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                                e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
                                rglog.error("调用通道<{}>的<{}-{}>服务失败后的异常处理调用异常:{}", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(),
                                        channelCallCfg.getCallChannelTxnName(), byteArrayOutputStream.toString());
                            }
                        }
                        rglog.error("调用通道<{}>的<{}-{}>服务{}，交易结束!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(),
                                channelCallCfg.getCallChannelTxnName(), TransStatusEnum.TRANS_TIMEOUT.equals(transStatusEnum) ? "超时" : "失败");
                        String chnlCallResultKey = CHANNEL_CALL_RESULT + channelCallCfg.getCallChannelId() + channelCallCfg.getCallIndex() + channelCallCfg.getCallChannelTxn();
                        Map<String,String> respValueMap = (Map<String, String>) GlobalTransUtil.getCacheValue(chnlCallResultKey);
                        if (null != respValueMap && !StringUtil.isEmptyOrNull(respValueMap.get(TreeNodeConstant.RESP_CODE))){
                            if (OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(respValueMap.get(TreeNodeConstant.RESP_CODE))) {
                                throw new BizException(TransStatusEnum.TRANS_TIMEOUT.equals(transStatusEnum) ? OltpRpcdEnum.BIZ_PROCESS_TIMEOUT : OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                            }else {
                                throw new BizException(respValueMap.get(TreeNodeConstant.RESP_CODE), respValueMap.get(TreeNodeConstant.RESP_DESC));
                            }
                        }else {
                            throw new BizException(TransStatusEnum.TRANS_TIMEOUT.equals(transStatusEnum) ? OltpRpcdEnum.BIZ_PROCESS_TIMEOUT : OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                        }
                    }else {
                        /* 当前通道调用失败不影响交易且未配置失败及超时的调用序号，调用序号直接赋值下一个正常调用的序号 */
                        if (StringUtil.isEmptyOrNull(nextCallIndex)) {
                            nextCallIndex = channelCallCfg.getNextCallIndex();
                        }
                    }
                }
                if (!StringUtil.isEmptyOrNull(nextCallIndex)) {
                    callServiceCore(txnInfo, nextCallIndex, callIndex, orderInfo, bizScene, request);
                }
            }
        }
    }

    /**
     * 通道服务调用
     *
     * @param txnInfo        交易配置信息
     * @param callIndex      当前调用序号
     * @param channelCallCfg 当前通道调用配置信息
     * @param orderInfo      订单信息
     * @param request        交易请求对象
     * @return 通道调用结果
     * @throws Exception 异常
     */
    private TransStatusEnum callChannelService(TxnInfo txnInfo, String callIndex, ChannelCallCfg channelCallCfg, OrderInfo orderInfo, T request) throws Exception {
        S callResponse = null;
        TransStatusEnum transStatusEnum = TransStatusEnum.SYSTEM_REJECT;
        /* Step1：通道服务调用前处理 */
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        Object channelInstance = callIndex.equals(FIRST_CHANNEL_CALL_INDEX) ? this : channelClasz.newInstance();
        Method callPreProcMethod = channelClasz.getMethod("callPreProc", TxnInfo.class, ChannelCallCfg.class, OrderInfo.class);
        R callRequest = (R) callPreProcMethod.invoke(channelInstance, txnInfo, channelCallCfg, orderInfo);
        if (null == callRequest) {
            rglog.error("调用通道<{}>的<{}-{}>服务预处理返回请求对象为null，交易结束！", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
            throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
        }
        /* Step2：通道服务调用前登记支付订单信息 */
        PayOrderInfo payOrderInfo = null;
        if (AppParamConstant.YES.equals(channelCallCfg.getRegisterPayOrderFlag())) {
            Method generatePayOrderInfoMethod = channelClasz.getMethod("generatePayOrderInfo", ChannelCallCfg.class, OrderInfo.class, Object.class);
            payOrderInfo = (PayOrderInfo) generatePayOrderInfoMethod.invoke(channelInstance, channelCallCfg, orderInfo, callRequest);
            if (null == payOrderInfo) {
                rglog.error("调用通道<{}>的<{}-{}>服务需要登记支付订单表，但是通道服务实现中未对支付订单信息进行赋值!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            } else {
                OrderService orderService = new OrderServiceImpl();
                if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
                    rglog.error("调用通道<{}>的<{}-{}>服务登记支付订单信息失败,交易终止,支付订单信息:<{}>", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(), JSON.toJSONString(payOrderInfo));
                    throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                }
                if (null == orderInfo.getPayOrderInfoList()) {
                    List<PayOrderInfo> payOrderInfoList = new ArrayList<>();
                    payOrderInfoList.add(payOrderInfo);
                    orderInfo.setPayOrderInfoList(payOrderInfoList);
                } else {
                    orderInfo.getPayOrderInfoList().add(payOrderInfo);
                }
            }
        }
        try {
            /* Step3：通道服务调用 */
            Method callProcMethod = channelClasz.getMethod("callProc", ChannelCallCfg.class, Object.class);
            callResponse = (S) callProcMethod.invoke(channelInstance, channelCallCfg, callRequest);
            transStatusEnum = parseCallResult(txnInfo, channelCallCfg, callResponse);
            /* Step3.1：通道服务异步调用，且需等待异步调用结果 */
            if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
                if (AppParamConstant.YES.equals(channelCallCfg.getSyncWaitResult()) && TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)) {
                    String queryGapType = ("0".equals(channelCallCfg.getSyncQueryGapType()) || "1".equals(channelCallCfg.getSyncQueryGapType())) ? channelCallCfg.getSyncQueryGapType() : "0";
                    int queryRepeatNum = channelCallCfg.getSyncQueryRepeatNum() > 0 ? channelCallCfg.getSyncQueryRepeatNum() : 1;
                    int queryRepeatTime = channelCallCfg.getSyncQueryRepeatTime() > 0 ? channelCallCfg.getSyncQueryRepeatTime() : 3000;
                    for (int i = 0; i < queryRepeatNum; i++) {
                        int sleepTime = "0".equals(queryGapType) ? queryRepeatTime : queryRepeatTime * (int) Math.pow(2.0, i);
                        Thread.sleep(sleepTime);
                        rglog.info("第<{}>次查询通道<{}>的<{}-{}>服务调用结果!", i + 1, channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
                        Method querySyncCallResultMethod = channelClasz.getMethod("querySyncCallResult", PayOrderInfo.class, Object.class);
                        callResponse = (S) querySyncCallResultMethod.invoke(channelInstance, payOrderInfo, callRequest);
                        transStatusEnum = parseCallResult(txnInfo, channelCallCfg, callResponse);
                        if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)) {
                            break;
                        }
                    }
                } else {
                    rglog.debug("调用通道<{}>的<{}-{}>服务为异步调用,调用结果通过异步服务处理！",
                            channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
                    callResponse = null;
                }
            }
        } catch (Exception e) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("调用通道<{}>的<{}-{}>服务异常,交易状态按失败处理,异常原因:{}",
                    channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(), byteArrayOutputStream.toString());
        } finally {
            /* Step3.2：基于通道调用结果对订单信息进行赋值修改 */
            Method callResultOrderProcMethod = channelClasz.getMethod("callResultOrderProc", OrderInfo.class, String.class, TransStatusEnum.class, Object.class);
            OrderInfo updateOrderInfo = (OrderInfo) callResultOrderProcMethod.invoke(channelInstance, orderInfo, channelCallCfg.getCallIndex(), transStatusEnum, callResponse);
            /* Step3.3：根据通道调结果回调交易服务中的结果处理方法进行业务控制处理，如基于通道返回的业务结果更改交易状态，同时可对订单信息进行重新赋值 */
            transStatusEnum = channelCallResultProc(request, txnInfo, channelCallCfg, transStatusEnum, callResponse, updateOrderInfo);
            rglog.info("通道<{}>的<{}-{}>服务调用结果为<{}-{}>", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(),
                    transStatusEnum.getStatus(), transStatusEnum.getDesc());
            /* Step3.4：基于通道调用结果进行其它客户化的处理 */
            invokeBizAnnoMethod(BIZ_RESULT.class, channelCallCfg, transStatusEnum, callResponse, updateOrderInfo);
            /* Step3.5：更新订单信息 */
            updateOrderInfo(txnInfo, channelCallCfg, transStatusEnum, updateOrderInfo, orderInfo);
        }
        return transStatusEnum;
    }

    /**
     * 系统本地服务调用
     *
     * @param txnInfo        交易配置信息
     * @param channelCallCfg 当前通道调用配置信息
     * @param orderInfo      订单信息
     * @param bizScene       业务场景
     * @param request        交易请求对象
     * @throws Exception 异常
     */
    private void callLocalService(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo, String bizScene, T request) throws Exception {
        int iReturnCode;
        String serviceName = channelCallCfg.getCallChannelImpl().trim();
        if (serviceName.contains(".")) {
            serviceName = serviceName.substring(serviceName.lastIndexOf(".") + 1);
        }
        if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
            AsynNotify asynNotify = new AsynNotify();
            int callGapType = ("0".equals(channelCallCfg.getSyncQueryGapType()) || "1".equals(channelCallCfg.getSyncQueryGapType())) ? Integer.parseInt(channelCallCfg.getSyncQueryGapType()) : 0;
            int callRepeatNum = channelCallCfg.getSyncQueryRepeatNum() > 0 ? channelCallCfg.getSyncQueryRepeatNum() : 1;
            int callRepeatTime = channelCallCfg.getSyncQueryRepeatTime() > 0 ? channelCallCfg.getSyncQueryRepeatTime() : 3000;
            iReturnCode = asynNotify.transactionNotice(serviceName, callRepeatNum, callGapType, callRepeatTime);
            rglog.info("异步调用本地服务<{}-{}>,异步调用方式:<{}>,异步调用次数:<{}>,异步调用时间间隔:<{}>,调用结果:<{}>",
                    serviceName, channelCallCfg.getCallChannelTxnName(), callGapType, callRepeatNum, callRepeatTime, iReturnCode);
        } else {
            Schedule schedule = (Schedule) ObjectPool.getObject(Schedule.class);
            schedule.reset();
            schedule.setBaseSchedule(new AbstractSchedule() {
                @Override
                public int initService(String ServiceName) {
                    return 0;
                }

                @Override
                public int termService(String ServiceName) {
                    return 0;
                }

                @Override
                public int service(String ServiceName, int Label) {
                    return 0;
                }
            });
            iReturnCode = schedule.callService(serviceName, 0);
            ObjectPool.returnObject(schedule);
            rglog.info("同步调用本地服务<{}-{}>,调用结果:<{}>", serviceName, channelCallCfg.getCallChannelTxnName(), iReturnCode);
        }
        if (0 != iReturnCode && AppParamConstant.YES.equals(channelCallCfg.getImpactTxnFlag())) {
            rglog.error("调用本系统原子组件服务<{}>失败,iReturnCode:<{}>,交易结束!", serviceName, iReturnCode);
            throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
        } else {
            String nextCallIndex = (0 == iReturnCode) ? channelCallCfg.getNextCallIndex() : channelCallCfg.getFailCallIndex();
            if (!StringUtil.isEmptyOrNull(nextCallIndex)) {
                callServiceCore(txnInfo, nextCallIndex, channelCallCfg.getCallIndex(), orderInfo, bizScene, request);
            }
        }
    }

    /**
     * 非正常情况后续通道服务调用
     *
     * @param txnInfo       交易配置信息
     * @param channelId     当前调用通道标识
     * @param nextCallIndex 下个调用序号
     * @param callIndex     当前调用序号
     * @param lastCallIndex 上次调用序号
     * @param orderInfo     订单信息
     * @param bizScene      业务场景
     * @param request       交易请求对象
     * @throws Exception 异常
     */
    private void callNextChannelService(TxnInfo txnInfo, String channelId, String nextCallIndex, String callIndex, String lastCallIndex, OrderInfo orderInfo, String bizScene, T request) throws Exception {
        if (!StringUtil.isEmptyOrNull(nextCallIndex)) {
            /* Step1：存在后续调用通道，继续调用后续通道 */
            callServiceCore(txnInfo, nextCallIndex, callIndex, orderInfo, bizScene, request);
        } else {
            if (null != orderInfo && null != orderInfo.getUserOrderInfo() && null != orderInfo.getMchntOrderInfoList() &&
                    OrderStatusEnum.INIT.getStatus().equals(orderInfo.getUserOrderInfo().getOrderStatus())) {
                /* Step2：不存在后续调用通道，以最后一次通道调用结果更新订单信息 */
                rglog.info("当前交易<{}-{}>在通道标识为<{}>,调用序号为<{}>的通道服务调用后没有后续通道服务调用，以最后一次登记的支付订单状态为准更新用户订单及商户订单!",
                        txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(), channelId, callIndex);
                Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().max(Comparator.comparing(PayOrderInfo::getUpdateTime));
                if (!payOrderInfoOpt.isPresent()) {
                    /* Step2.1：若前一次调用没有登记支付订单，则按照登记订单时间倒序排序，取最后一次登记的支付订单进行更新 */
                    payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().max(Comparator.comparing(PayOrderInfo::getCreateTime));
                }
                if (payOrderInfoOpt.isPresent()) {
                    /* Step2.2：用户订单信息状态赋值 */
                    orderInfo.getUserOrderInfo().setTransStatus(payOrderInfoOpt.get().getTransStatus());
                    orderInfo.getUserOrderInfo().setBizStatus(payOrderInfoOpt.get().getBizStatus());
                    orderInfo.getUserOrderInfo().setOrderStatus((BizStatusEnum.FINISH.getStatus().equals(payOrderInfoOpt.get().getBizStatus()) ? OrderStatusEnum.FINISH.getStatus() : OrderStatusEnum.INIT.getStatus()));
                    /* Step2.3：商户订单信息状态赋值 */
                    orderInfo.getMchntOrderInfoList().forEach(item -> {
                        item.setTransStatus(orderInfo.getUserOrderInfo().getTransStatus());
                        item.setBizStatus(orderInfo.getUserOrderInfo().getBizStatus());
                    });
                    /* Step2.4：更新用户及商户订单信息 */
                    OrderService orderService = new OrderServiceImpl();
                    boolean orderProcFlag = orderService.updateOrderInfo(orderInfo.getUserOrderInfo(), orderInfo.getMchntOrderInfoList(), null, null);
                    if (!orderProcFlag) {
                        rglog.error("交易<{}-{}>更新订单表失败，交易结束!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
                        throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                    }
                } else {
                    rglog.error("无法获取最后一次登记的支付订单信息，无法确定订单的最终调用结果，交易按超时处理!");
                    throw new BizException(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT);
                }
            }
        }
    }

    /**
     * 基于通道调用结果更新用户、商户及支付订单信息
     *
     * @param txnInfo         交易配置信息
     * @param channelCallCfg  通道服务配置信息
     * @param transStatusEnum 通道调用结果
     * @param updateOrderInfo 需要更新的订单信息
     * @param orderInfo       当前交易所涉及到的所有订单信息
     * @throws Exception 异常
     */
    private void updateOrderInfo(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, OrderInfo updateOrderInfo, OrderInfo orderInfo) throws Exception {
        OrderService orderService = new OrderServiceImpl();
        String transStatus = transStatusEnum.getStatus();
        String bizStatus = TransStatusEnum.TRANS_TIMEOUT.equals(transStatusEnum) ? BizStatusEnum.PROCESSING.getStatus() : BizStatusEnum.FAILED.getStatus();
        updateOrderInfo = (null == updateOrderInfo) ? new OrderInfo() : updateOrderInfo;

        /* Step1：基于通道调用结果更新支付订单表的状态 */
        PayOrderInfo payOrderInfo = null;
        if (null != updateOrderInfo.getPayOrderInfoList()) {
            Optional<PayOrderInfo> payOrderInfoOpt = updateOrderInfo.getPayOrderInfoList().stream().filter(item ->
                    item.getMsgDstId().equals(channelCallCfg.getCallChannelId()) &&
                            item.getDstCallIndex().equals(channelCallCfg.getCallIndex())).findFirst();
            if (payOrderInfoOpt.isPresent()) {
                payOrderInfo = payOrderInfoOpt.get();
                transStatus = payOrderInfo.getTransStatus();
                bizStatus = payOrderInfo.getBizStatus();
            } else if (AppParamConstant.YES.equals(channelCallCfg.getRegisterPayOrderFlag())) {
                Optional<PayOrderInfo> regPayOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item ->
                        item.getMsgDstId().equals(channelCallCfg.getCallChannelId()) &&
                                item.getDstCallIndex().equals(channelCallCfg.getCallIndex())).findFirst();
                if (regPayOrderInfoOpt.isPresent()) {
                    rglog.warn("交易<{}-{}>在callResultOrderProc中有登记支付订单，但是调用结束后未返回要更新的支付订单信息，平台默认按交易状态更新支付订单状态!",
                            txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
                    payOrderInfo = regPayOrderInfoOpt.get();
                    payOrderInfo.setTransStatus(transStatusEnum.getStatus());
                    payOrderInfo.setBizStatus(bizStatus);
                    rglog.info("通道<{}>的<{}-{}>服务调用处理后的支付订单状态,交易状态:{},业务状态:{}",
                            channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(), payOrderInfo.getTransStatus(), payOrderInfo.getBizStatus());
                    updateOrderInfo.setPayOrderInfoList(Collections.singletonList(payOrderInfo));
                } else {
                    rglog.error("交易<{}-{}>在callResultOrderProc中登记支付订单信息异常,交易失败!",
                            txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
                    throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                }
            }
        }
        /* Step2：通道调用失败且影响交易时，且存在用户订单及商户订单，若通道调用未对要更新的订单进行赋值时，底层采用兜底方式处理 */
        if (!TransStatusEnum.TRANS_SUCC.equals(transStatusEnum) && AppParamConstant.YES.equals(channelCallCfg.getImpactTxnFlag())) {
            if (null == updateOrderInfo.getUserOrderInfo() && null != orderInfo.getUserOrderInfo()) {
                rglog.info("通道<{}>的<{}-{}>服务调用处理后,订单状态更新前的用户订单状态,交易状态:{},业务状态:{},订单状态:{}",
                        channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(),
                        orderInfo.getUserOrderInfo().getTransStatus(), orderInfo.getUserOrderInfo().getBizStatus(), orderInfo.getUserOrderInfo().getOrderStatus());
                orderInfo.getUserOrderInfo().setTransStatus(transStatus);
                orderInfo.getUserOrderInfo().setBizStatus(bizStatus);
                updateOrderInfo.setUserOrderInfo(orderInfo.getUserOrderInfo());
                rglog.info("底层基于业务流程调整后的用户订单状态,交易状态:{},业务状态:{},订单状态:{}",
                        updateOrderInfo.getUserOrderInfo().getTransStatus(), updateOrderInfo.getUserOrderInfo().getBizStatus(), updateOrderInfo.getUserOrderInfo().getOrderStatus());
            }
            if (null == updateOrderInfo.getMchntOrderInfoList() && null != orderInfo.getMchntOrderInfoList()) {
                rglog.info("通道<{}>的<{}-{}>服务调用处理后,订单状态更新前的商户订单状态,交易状态:{},业务状态:{}",
                        channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(),
                        orderInfo.getMchntOrderInfoList().get(0).getTransStatus(), orderInfo.getMchntOrderInfoList().get(0).getBizStatus());
                for (MchntOrderInfo mchntOrderInfo : orderInfo.getMchntOrderInfoList()) {
                    mchntOrderInfo.setTransStatus(transStatus);
                    mchntOrderInfo.setBizStatus(bizStatus);
                }
                updateOrderInfo.setMchntOrderInfoList(orderInfo.getMchntOrderInfoList());
                rglog.info("底层基于业务流程调整后的商户订单状态,交易状态:{},业务状态:{}",
                        updateOrderInfo.getMchntOrderInfoList().get(0).getTransStatus(), updateOrderInfo.getMchntOrderInfoList().get(0).getBizStatus());
            }
        } else {
            if (null != updateOrderInfo.getUserOrderInfo()) {
                rglog.info("调用通道<{}>的<{}-{}>服务后，用户订单待更新的交易状态为:{},业务状态为:{},订单状态为:{}",
                        channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(),
                        updateOrderInfo.getUserOrderInfo().getTransStatus(), updateOrderInfo.getUserOrderInfo().getBizStatus(), updateOrderInfo.getUserOrderInfo().getOrderStatus());
            }
            if (null != updateOrderInfo.getMchntOrderInfoList() && !updateOrderInfo.getMchntOrderInfoList().isEmpty()) {
                rglog.info("调用通道<{}>的<{}-{}>服务后，商户订单待更新的交易状态为:{},业务状态为:{}",
                        channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(),
                        updateOrderInfo.getMchntOrderInfoList().get(0).getTransStatus(), updateOrderInfo.getMchntOrderInfoList().get(0).getBizStatus());
            }
            if (null != payOrderInfo) {
                rglog.info("调用通道<{}>的<{}-{}>服务后，支付订单待更新的交易状态为:{},业务状态为:{}",
                        channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(), payOrderInfo.getTransStatus(), payOrderInfo.getBizStatus());
            }
        }
        /* Step3：更新订单状态 */
        if (null != updateOrderInfo.getUserOrderInfo() || null != updateOrderInfo.getMchntOrderInfoList() ||
                null != updateOrderInfo.getMchntOrderDetailList() || null != updateOrderInfo.getPayOrderInfoList()) {
            boolean orderProcFlag = orderService.updateOrderInfo(updateOrderInfo);
            if (!orderProcFlag) {
                rglog.error("交易<{}-{}>更新订单表失败，交易结束!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
            /* Step3.1：更新订单并同步更新orderInfo对象中的数据 */
            if (null != updateOrderInfo.getUserOrderInfo()) {
                orderInfo.setUserOrderInfo(updateOrderInfo.getUserOrderInfo());
            }
            if (null != updateOrderInfo.getMchntOrderInfoList()) {
                orderInfo.setMchntOrderInfoList(updateOrderInfo.getMchntOrderInfoList());
            }
            if (null != updateOrderInfo.getMchntOrderDetailList()) {
                orderInfo.setMchntOrderDetailList(updateOrderInfo.getMchntOrderDetailList());
            }
            if (null != updateOrderInfo.getPayOrderInfoList()) {
                for (PayOrderInfo updatePayOrderInfo : updateOrderInfo.getPayOrderInfoList()) {
                    Optional<PayOrderInfo> updPayOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item ->
                            item.getMsgDstId().equals(updatePayOrderInfo.getMsgDstId()) && item.getDstCallIndex().equals(updatePayOrderInfo.getDstCallIndex())).findFirst();
                    if (updPayOrderInfoOpt.isPresent()) {
                        orderInfo.getPayOrderInfoList().remove(updPayOrderInfoOpt.get());
                        orderInfo.getPayOrderInfoList().add(updatePayOrderInfo);
                    }
                }
            }
        }
    }

    /**
     * 解析通道服务调用结果
     *
     * @param txnInfo        交易配置信息
     * @param channelCallCfg 通道服务配置信息
     * @param response       通道调用结果
     * @return 交易状态
     */
    private TransStatusEnum parseCallResult(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, S response) throws Exception {
        if (null == response) {
            rglog.error("调用通道<{}>的<{}-{}>服务返回值为null，交易状态按超时处理!",
                    channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
            return TransStatusEnum.TRANS_TIMEOUT;
        }
        Map<String,String> respValueMap = getRespCodeValue(response);
        String chnlCallResultKey = CHANNEL_CALL_RESULT + channelCallCfg.getCallChannelId() + channelCallCfg.getCallIndex() + channelCallCfg.getCallChannelTxn();
        GlobalTransUtil.setCacheValue(chnlCallResultKey,respValueMap);
        String respCodeValue = respValueMap.get(TreeNodeConstant.RESP_CODE);
        rglog.debug("交易<{}-{}>调用通道<{}>的<{}-{}>服务业务返回码为:{}", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(),
                channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(), respCodeValue);
        if (!StringUtil.isEmptyOrNull(respCodeValue)) {
            if (OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(respCodeValue)) {
                return TransStatusEnum.TRANS_SUCC;
            } else if (OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode().equals(respCodeValue)) {
                return TransStatusEnum.TRANS_TIMEOUT;
            } else {
                return TransStatusEnum.SYSTEM_REJECT;
            }
        } else {
            rglog.warn("交易<{}-{}>调用通道<{}>的<{}-{}>服务返回错误码为空:{}，交易状态按超时处理!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(),
                    channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName(), JSON.toJSONString(response));
            return TransStatusEnum.TRANS_TIMEOUT;
        }
    }

    /**
     * 获取通道业务响应结果
     *
     * @param response 通道调用返回对象
     * @return 业务响应结果
     */
    private Map<String,String> getRespCodeValue(S response) {
        Map<String,String> respValueMap = new HashMap<>();
        Class clasz = response.getClass();
        try {
            Field respCodeField = clasz.getDeclaredField(TreeNodeConstant.RESP_CODE);
            Field respDescField = clasz.getDeclaredField(TreeNodeConstant.RESP_DESC);
            respCodeField.setAccessible(true);
            String respCodeValue = (String) respCodeField.get(response);
            respValueMap.put(TreeNodeConstant.RESP_CODE,respCodeValue);
            respDescField.setAccessible(true);
            String respDescValue = (String) respDescField.get(response);
            respValueMap.put(TreeNodeConstant.RESP_DESC,respDescValue);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            try {
                Field resultField = clasz.getDeclaredField("result");
                resultField.setAccessible(true);
                Object resultValue = resultField.get(response);
                if (null != resultValue) {
                    Class resultClasz = resultValue.getClass();
                    while (null != resultClasz) {
                        Field[] fields = resultClasz.getDeclaredFields();
                        for (Field field : fields) {
                            if (field.getName().equals(TreeNodeConstant.RESP_CODE)) {
                                field.setAccessible(true);
                                String respCodeValue = (String) field.get(resultValue);
                                respValueMap.put(TreeNodeConstant.RESP_CODE,respCodeValue);
                            }
                            if (field.getName().equals(TreeNodeConstant.RESP_DESC)) {
                                field.setAccessible(true);
                                String respDescValue = (String) field.get(resultValue);
                                respValueMap.put(TreeNodeConstant.RESP_DESC,respDescValue);
                            }
                        }
                        resultClasz = resultClasz.getSuperclass();
                    }
                }
            } catch (NoSuchFieldException | IllegalAccessException noSuchFieldException) {
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                noSuchFieldException.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
                rglog.error("通道调用业务响应结果异常：{}", byteArrayOutputStream.toString());
            }
        }
        return respValueMap;
    }

    /**
     * 通道调用结果业务层处理
     *
     * @param request         交易请求对象
     * @param txnInfo         交易配置信息
     * @param channelCallCfg  通道配置信息
     * @param transStatusEnum 通道调用状态
     * @param response        通道调用返回结果
     * @param orderInfo       订单信息
     * @return 通道调用结果
     */
    private TransStatusEnum channelCallResultProc(T request, TxnInfo txnInfo, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, S response, OrderInfo orderInfo) {
        try {
            ServiceEntity serviceEntity = BulletinBoard.getService(txnInfo.getSrcTxnAuthCfg().getServiceName());
            String serviceName = serviceEntity.getClassPath() + "." + txnInfo.getSrcTxnAuthCfg().getServiceName();
            Class clasz = Class.forName(serviceName);
            Method method = clasz.getMethod("channelCallResultProc", Object.class, ChannelCallCfg.class, TransStatusEnum.class, Object.class, OrderInfo.class);
            TransStatusEnum txnTransStatusEnum = (TransStatusEnum) method.invoke(clasz.newInstance(), request, channelCallCfg, transStatusEnum, response, orderInfo);
            if (null != txnTransStatusEnum && !txnTransStatusEnum.equals(transStatusEnum)){
                String chnlCallResultKey = CHANNEL_CALL_RESULT + channelCallCfg.getCallChannelId() + channelCallCfg.getCallIndex() + channelCallCfg.getCallChannelTxn();
                Map<String,String> respValueMap = (Map<String, String>) GlobalTransUtil.getCacheValue(chnlCallResultKey);
                Map<String,String> resetRespValueMap = getRespCodeValue(response);
                GlobalTransUtil.setCacheValue(chnlCallResultKey,resetRespValueMap);
                rglog.info("交易<{}-{}>基于通道调用结果,将交易状态由<{}-{}>重置为了<{}-{}>,通道响应码由<{}-{}>重置为了<{}-{}>",txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(),
                        transStatusEnum.getStatus(), transStatusEnum.getDesc(), txnTransStatusEnum.getStatus(),txnTransStatusEnum.getDesc(),(null == respValueMap)?null:respValueMap.get(TreeNodeConstant.RESP_CODE),
                        (null == respValueMap)?null:respValueMap.get(TreeNodeConstant.RESP_DESC), resetRespValueMap.get(TreeNodeConstant.RESP_CODE),resetRespValueMap.get(TreeNodeConstant.RESP_DESC));
                return txnTransStatusEnum;
            }else {
                return (null == txnTransStatusEnum) ? transStatusEnum : txnTransStatusEnum;
            }
        } catch (NoSuchMethodException e) {
            rglog.warn("交易<{}-{}>未实现channelCallResultProc方法，默认不进行处理!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            return transStatusEnum;
        } catch (Exception e) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("交易<{}-{}>实现channelCallResultProc方法异常，按调用超时处理:{}", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(), byteArrayOutputStream.toString());
            if (null != orderInfo && null != orderInfo.getPayOrderInfoList() && !orderInfo.getPayOrderInfoList().isEmpty()) {
                Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item ->
                        item.getMsgDstId().equals(channelCallCfg.getCallChannelId()) &&
                                item.getDstCallIndex().equals(channelCallCfg.getCallIndex())).findFirst();
                if (payOrderInfoOpt.isPresent()) {
                    TransStatusEnum callResultStatus = TransStatusEnum.getTransStatusEnum(payOrderInfoOpt.get().getTransStatus());
                    rglog.warn("将订单状态由调用后的<{}-{}>状态更新为<{}-{}>状态!", Objects.requireNonNull(callResultStatus).getStatus(), callResultStatus.getDesc(), TransStatusEnum.TRANS_TIMEOUT.getStatus(), TransStatusEnum.TRANS_TIMEOUT.getDesc());
                    payOrderInfoOpt.get().setTransStatus(TransStatusEnum.TRANS_TIMEOUT.getStatus());
                }
            }
            return TransStatusEnum.TRANS_TIMEOUT;
        }
    }

    /**
     * 通道服务调用前业务检查
     *
     * @param txnInfo        交易配置信息
     * @param channelCallCfg 通道配置信息
     * @param orderInfo      订单信息
     * @param request        交易请求对象
     * @return 业务检查结果
     */
    private CheckResultEnum channelCallPreCheck(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo, T request) {
        try {
            if (AppParamConstant.YES.equals(channelCallCfg.getRecordStatus())) {
                ServiceEntity serviceEntity = BulletinBoard.getService(txnInfo.getSrcTxnAuthCfg().getServiceName());
                String serviceName = serviceEntity.getClassPath() + "." + txnInfo.getSrcTxnAuthCfg().getServiceName();
                Class clasz = Class.forName(serviceName);
                Method method = clasz.getMethod("channelCallPreCheck", Object.class, ChannelCallCfg.class, OrderInfo.class);
                CheckResultEnum checkResultEnum = (CheckResultEnum) method.invoke(clasz.newInstance(), request, channelCallCfg, orderInfo);
                rglog.info("调用通道<{}>的<{}-{}>服务前检查结果为:<{}-{}>", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(),
                        channelCallCfg.getCallChannelTxnName(), (null == checkResultEnum) ? "null" : checkResultEnum.getCode(), (null == checkResultEnum) ? "null" : checkResultEnum.getDesc());
                return (null == checkResultEnum) ? CheckResultEnum.PASSED : checkResultEnum;
            } else {
                rglog.info("当前要调用通道<{}>的<{}-{}>为无效配置记录,忽略继续调用下个通道!", channelCallCfg.getCallChannelId(), channelCallCfg.getCallChannelTxn(), channelCallCfg.getCallChannelTxnName());
                return CheckResultEnum.NEXT;
            }
        } catch (NoSuchMethodException e) {
            rglog.warn("交易<{}-{}>未实现channelCallPreCheck方法，默认不进行检查!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            return CheckResultEnum.PASSED;
        } catch (Exception e) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("对交易<{}-{}>进行channelCallPreCheck异常，按检查不通过处理:{}", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(), byteArrayOutputStream.toString());
            return CheckResultEnum.REFUSE;
        }
    }

    /**
     * 根据通道调用序号获取对应的业务场景的通道服务配置
     *
     * @param txnInfo   交易配置信息
     * @param bizScene  业务场景
     * @param callIndex 通道调用序号
     * @param request   交易请求对象
     * @return 通道调用配置信息
     */
    private ChannelCallCfg channelCallSceneDiscern(TxnInfo txnInfo, String bizScene, String callIndex, T request) {
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(callIndex) && item.getBizScene().equals(bizScene)).collect(Collectors.toList());
        if (channelCallCfgList.isEmpty()) {
            rglog.error("交易<{}-{}>未配置通道调用服务，或者调用序号为<{}>通道服务接口实现类未配置!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(), callIndex);
            throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
        } else {
            if (channelCallCfgList.size() == 1) {
                return channelCallCfgList.get(0);
            } else {
                try {
                    ServiceEntity serviceEntity = BulletinBoard.getService(txnInfo.getSrcTxnAuthCfg().getServiceName());
                    String serviceName = serviceEntity.getClassPath() + "." + txnInfo.getSrcTxnAuthCfg().getServiceName();
                    Class clasz = Class.forName(serviceName);
                    Method method = clasz.getMethod("channelCallSceneDiscern", Object.class, List.class);
                    ChannelCallCfg channelCallCfg = (ChannelCallCfg) method.invoke(clasz.newInstance(), request, channelCallCfgList);
                    if ((null == channelCallCfg)) {
                        rglog.error("交易<{}-{}>在通道调用序号为<{}>的channelCallSceneDiscern实现中返回通道调用配置为空,请基于业务场景返回对应的通道调用配置!",
                                txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(), callIndex);
                        throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                    } else {
                        return channelCallCfg;
                    }
                } catch (Exception e) {
                    if (e instanceof BizException) {
                        throw (BizException) e;
                    } else {
                        rglog.error("交易<{}-{}>存在通道调用序号为<{}>的多种业务调用流程，请在<{}>中实现channelCallSceneDiscern的方法，返回对应调用序号的通道配置信息!",
                                txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName(), callIndex, txnInfo.getSrcTxnAuthCfg().getServiceName());
                        throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
                    }
                }
            }
        }
    }

    /**
     * 业务自定义注解类执行
     *
     * @param annoClasz 注解类
     * @param requests  调用方法请求参数集
     */
    public void invokeBizAnnoMethod(Class annoClasz, Object... requests) throws Exception {
        Method[] methods = this.getClass().getDeclaredMethods();
        for (Method method : methods) {
            boolean isThisMethod = false;
            boolean methodHasAnno = method.isAnnotationPresent(annoClasz);
            if (methodHasAnno) {
                Type[] genericParameterTypes = method.getGenericParameterTypes();
                if (requests.length == genericParameterTypes.length) {
                    for (int i = 0; i < requests.length; i++) {
                        if (genericParameterTypes[i].getTypeName().equals(requests[i].getClass().getName())) {
                            isThisMethod = true;
                        } else if (genericParameterTypes[i] instanceof ParameterizedType) {
                            Class[] claszs = requests[i].getClass().getInterfaces();
                            String name = method.getParameterTypes()[i].getTypeName();
                            List<String> claszNames = Arrays.stream(claszs).map(Class::getName).collect(Collectors.toList());
                            if (claszNames.contains(name)) {
                                isThisMethod = true;
                            }
                        }
                    }
                    if (isThisMethod) {
                        /* 执行对应的注解方法 */
                        rglog.info("正在执行注解类{}的自定义方法:{}", annoClasz.getName(), method.getName());
                        method.setAccessible(true);
                        method.invoke(this.getClass().newInstance(), requests);
                    }
                }
            }
        }
    }

    /**
     * 服务调用前处理
     *
     * @param txnInfo        交易配置信息
     * @param channelCallCfg 通道配置信息
     * @param orderInfo      订单信息
     * @return 服务调用前处理结果
     * @throws Exception 异常
     */
    public abstract R callPreProc(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception;

    /**
     * 生成支付订单信息
     *
     * @param channelCallCfg 通道配置信息
     * @param orderInfo      订单信息
     * @param request        服务调用前处理结果
     * @return 需要登记的支付订单信息
     * @throws Exception 异常
     */
    public abstract PayOrderInfo generatePayOrderInfo(ChannelCallCfg channelCallCfg, OrderInfo orderInfo, R request) throws Exception;

    /**
     * 服务调用
     *
     * @param channelCallCfg 通道配置信息
     * @param request        服务调用前处理结果
     * @return 通道服务调用返回结果, 若为异步调用，则返回BizResponse对象
     * @throws Exception 异常
     */
    public abstract S callProc(ChannelCallCfg channelCallCfg, R request) throws Exception;

    /**
     * 异步调用结果查询
     *
     * @param payOrderInfo 支付订单信息
     * @param request      原交易调用请求信息
     * @return 原交易调用结果
     */
    public abstract S querySyncCallResult(PayOrderInfo payOrderInfo, R request);

    /**
     * 服务调用结果处理（只对订单信息进行赋值）
     *
     * @param transStatusEnum 交易调用结果枚举
     * @param response        服务调用结果对象
     * @param orderInfo       订单信息
     * @param payOrderIndex   当前支付订单调用索引
     * @return 需要更新的订单信息
     * @throws Exception 异常
     */
    public abstract OrderInfo callResultOrderProc(OrderInfo orderInfo, String payOrderIndex, TransStatusEnum transStatusEnum, Object response) throws Exception;
}
